package cn.nexd.app.collector.presenter.collect;

import android.app.Activity;
import android.content.Context;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.CopyOnWriteArrayList;

import cn.nexd.app.collector.Configuration;
import cn.nexd.app.collector.application.NexdApplication;
import cn.nexd.app.collector.collect.SensorCollectListener;
import cn.nexd.app.collector.collect.SensorDetector;
import cn.nexd.app.collector.model.CollectConfig;
import cn.nexd.app.collector.util.UMengUtil;
import cn.nexd.sdk.collector.NexdCollector;
import cn.nexd.sdk.collector.NexdCollectorAgent;
import cn.nexd.sdk.collector.NexdCollectorConfiguration;
import cn.nexd.sdk.collector.NexdCollectorResult;
import cn.nexd.sdk.collector.NexdCollectorResultListener;
import cn.nexd.utils.framework.error.NexdCrashException;
import cn.nexd.utils.framework.tools.FileUtil;
import cn.nexd.utils.framework.tools.Logger;


/**
 * Created by wangxu on 16/9/9.
 */
public class CollectPresenter implements MainContract.Presenter {


    private static final String TAG = "CollectPresenter";

    private MainContract.View mainView;

    private SensorDetector sensorDetector; // 传感器

    private Context context;

    private NexdCollectorAgent agent;

    private CopyOnWriteArrayList<NexdCollectorResult> wifiRecordCollectResults; // wifi 采集记录容器

    private CopyOnWriteArrayList<NexdCollectorResult> beaconRecordCollectResults; // beacon 采集记录容器


    private CopyOnWriteArrayList<CopyOnWriteArrayList<NexdCollectorResult>> wifiTempCollectResult; // wifi 采集临时结果存储器
    private CopyOnWriteArrayList<CopyOnWriteArrayList<NexdCollectorResult>> beaconTempCollectResult; // beacon 采集临时结果存储器

    //  WiFi、beacon、sensor和 IOS 拼接组件
    private StringBuilder wifiStringBuilder;
    private StringBuilder beaconStringBuilder;
    private StringBuilder sensorStringBuilder;
    private StringBuilder iosStringBuilder;

    // 各文件存储路径
    private String wifiSavePath;
    private String beaconSavePath;
    private String sensorSavePath;
    private String iosSavePath;
    private String zipSrcSavePath;
    private String zipSavePath;

    // 采集器意外停止时,用来判断的标示
    private boolean isPauseCollection = false;
    // 环境参量返回值,用来记录,定时回调。
    private int environmentParam = 0;

    private boolean isWifi = true;

    private Timer timer;


    public CollectPresenter(Context context, MainContract.View mainView) {
        this.context = context;
        this.mainView = mainView;
        this.wifiStringBuilder = new StringBuilder();
        this.sensorStringBuilder = new StringBuilder();
        this.beaconStringBuilder = new StringBuilder();
        iosStringBuilder = new StringBuilder();
    }

    @Override
    public void init() {
    }
//
//    public boolean checkMemory () {
//        SDCardUtil.getAvailableBlocks(SDCardUtil.getSDCardPath()) <
//    }

    // 初始化采集需要的文件
    private void initCollect() {
        agent = NexdCollectorAgent.getCollectorAgent(context);
        wifiTempCollectResult = new CopyOnWriteArrayList<>();
        beaconTempCollectResult = new CopyOnWriteArrayList<>();
        wifiRecordCollectResults = new CopyOnWriteArrayList<>();
        beaconRecordCollectResults = new CopyOnWriteArrayList<>();
        isPauseCollection = false;
        timer = new Timer();
        timer.schedule(new EnvironmentCallBackRunnable(), 100, 2000);
    }

    // 开始采集,定义各种文件等
    public void startCollector(String floorId, String currentMallPy, String email) {
        // 初始化一些存储路径
        wifiSavePath = Configuration.getSavePath(Configuration.Path.SAVE_BASE_PATH) + currentMallPy + "/" + currentMallPy
                + "_" + floorId + "_" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "_" + email + ".wifi";
        beaconSavePath = Configuration.getSavePath(Configuration.Path.SAVE_BASE_PATH) + currentMallPy + "/" + currentMallPy
                + "_" + floorId + "_" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "_" + email + ".bluetooth";
        sensorSavePath = Configuration.getSavePath(Configuration.Path.SAVE_BASE_PATH) + currentMallPy + "/" + currentMallPy
                + "_" + floorId + "_" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "_" + email + ".sensor";
        iosSavePath = Configuration.getSavePath(Configuration.Path.SAVE_BASE_PATH) + currentMallPy + "/" + currentMallPy
                + "_" + floorId + "_" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "_" + email + ".ios";
        zipSrcSavePath = Configuration.getSavePath(Configuration.Path.SAVE_BASE_PATH) + currentMallPy + "/";
        zipSavePath = Configuration.getSavePath(Configuration.Path.SAVE_BASE_PATH) + currentMallPy
                + "_" + floorId + "_" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "_" + email + ".zip";
        initCollect();
        sensorDetector = new SensorDetector(context);
        NexdCollectorConfiguration.Builder builder = new NexdCollectorConfiguration.Builder();

        // 获取采集配置,目前 WiFi 和 蓝牙只有一个工作,故可直接获取。
        CollectConfig collectConfig = NexdApplication.getInstance().getCollectConfigs().get(0);

        if ("WIFI".equals(collectConfig.getCollectWay())) {
            Logger.debug(TAG, "wifi collect");
            builder.setWifiCollectorDelay(100);
            builder.setWifiCollectorEnable(true);
            builder.setWifiCollectorRate((int) collectConfig.getCollectSpeed());
            builder.setWifiResultCacheTime(collectConfig.getCollectTime());
            builder.setCollectorDelay(100);
            builder.setCollectorRate(1000);
            builder.setBeaconCollectorEnable(false);
            isWifi = true;
        } else {
            Logger.debug(TAG, "beacon collect");
            builder.setBeaconScanMode(NexdCollectorConfiguration.CollectorScanMode.SCAN_MODE_BALANCED);
            builder.setBeaconCollectorDelay(100);
            builder.setBeaconCollectorEnable(true);
            builder.setBeaconCollectorRate((int) collectConfig.getCollectSpeed());
            builder.setBeaconResultCacheTime(collectConfig.getCollectTime());
            builder.setCollectorDelay(100);
            builder.setCollectorRate(1000);
            builder.setWifiCollectorEnable(false);
            isWifi = false;
        }

        agent.startCollector(builder.build(), new NexdCollectorResultListener() {
            @Override
            public void onCollectorChanged(NexdCollector nexdCollector, final List<NexdCollectorResult> list) {
                if (list != null) {
                    environmentParam = list.size();
                    CopyOnWriteArrayList copyList = new CopyOnWriteArrayList(list);
                    if (isWifi) {
                        if (nexdCollector.getWifiCollectorState() == NexdCollector.CollectorState.ERROR_CODE_COLLECTOR_SUCCESS) {
                            wifiTempCollectResult.add(copyList);
                        } else {
                            isPauseCollection = true;
                            mainView.pauseCollection(nexdCollector.getBeaconCollectorState().getCollectorState());
                            stopCollector();
                        }
                    } else {
                        if (nexdCollector.getBeaconCollectorState() == NexdCollector.CollectorState.ERROR_CODE_COLLECTOR_SUCCESS) {
                            NexdApplication.getInstance().getSqlHelper().insertIfNotExist(copyList);
                            beaconTempCollectResult.add(copyList);
                        } else {
                            isPauseCollection = true;
                            mainView.pauseCollection(nexdCollector.getBeaconCollectorState().getCollectorState());
                            stopCollector();
                        }
                    }
                }
            }
        });

        sensorDetector.setSensorCollectListener(new SensorCollectListener() {
            @Override
            public void onSensorCycle(int step, float[] dataVector, long counter, long timestamp) {

                mainView.updateSensorStep(String.valueOf(step));
                wifiStringBuilder.append(appendWifiCollectResult(counter));
                beaconStringBuilder.append(appendBeaconCollectResult(counter));
                sensorStringBuilder.append(appendSensorCollectResult(counter, dataVector, timestamp));

                if (sensorStringBuilder.length() > 65535 * 4) {
                    new SaveThread(wifiStringBuilder.toString(), beaconStringBuilder.toString(), sensorStringBuilder.toString()).run();
                    wifiStringBuilder.setLength(0);
                    beaconStringBuilder.setLength(0);
                    sensorStringBuilder.setLength(0);
                }
            }
        });
    }

    private CopyOnWriteArrayList<NexdCollectorResult> getWifiCollectResult() {
        if (wifiTempCollectResult.size() > 0) {
            wifiRecordCollectResults = wifiTempCollectResult.get(0);
            wifiTempCollectResult.remove(0);
        }
        return wifiRecordCollectResults;
    }


    private CopyOnWriteArrayList<NexdCollectorResult> getBeaconCollectResult() {
        if (beaconTempCollectResult.size() > 0) {
            beaconRecordCollectResults = beaconTempCollectResult.get(0);
            beaconTempCollectResult.remove(0);
        }
        return beaconRecordCollectResults;
    }

    private String appendWifiCollectResult(long count) {
        StringBuilder wifiStringBuilder = new StringBuilder();
        synchronized (wifiRecordCollectResults) {
            CopyOnWriteArrayList<NexdCollectorResult> wifiList = getWifiCollectResult();
            wifiStringBuilder.append(count);
            for (NexdCollectorResult nexdCollectorResult : wifiList) {
                wifiStringBuilder.append(" ")
                        .append(nexdCollectorResult.getSingleSourceAddress())
                        .append(" ")
                        .append(nexdCollectorResult.getSingleSourceStrength());
            }
            wifiStringBuilder.append("\n");
        }
        return wifiStringBuilder.toString();
    }

    private String appendBeaconCollectResult(long count) {
        StringBuilder beaconStringBuilder = new StringBuilder();
        synchronized (beaconRecordCollectResults) {
            CopyOnWriteArrayList<NexdCollectorResult> beaconList = getBeaconCollectResult();
            beaconStringBuilder.append(count);
            for (NexdCollectorResult nexdCollectorResult : beaconList) {
                beaconStringBuilder.append(" ")
                        .append(nexdCollectorResult.getSingleSourceAddress())
                        .append(" ")
                        .append(nexdCollectorResult.getSingleSourceStrength());
            }
            beaconStringBuilder.append("\n");
        }
        return beaconStringBuilder.toString();
    }

    private String appendSensorCollectResult(long counter, float[] dataVector, long timestamp) {
        StringBuilder stringBuffer_sensor = new StringBuilder();
        stringBuffer_sensor.append(counter).append(" ");
        for (int i = 1; i < 44; i++) {
            stringBuffer_sensor.append(dataVector[i]).append(' ');
        }
        stringBuffer_sensor.append(timestamp).append(' ');
        for (int i = 44; i < 69; i++) {
            stringBuffer_sensor.append(dataVector[i]).append(' ');
        }
        stringBuffer_sensor.append("\n");
        return stringBuffer_sensor.toString();
    }

    public void stopCollector() {
        sensorDetector.unRegisterListener();
        agent.stopCollector();
        timer.cancel();
        mainView.updateEnvironment(String.valueOf(0));
        if (!isPauseCollection) {
            compressFile();
            isPauseCollection = false;
        }
    }

    @Override
    public void saveData() {
        compressFile();
    }

    @Override
    public void cancelData() {
        try {
            FileUtil.deleteFile(zipSrcSavePath);
        } catch (IOException e) {
            e.printStackTrace();
            UMengUtil.getInstance().reportError(context, e);
            NexdCrashException.getInstance().reportException(e);
        }
    }

    private void compressFile() {
        mainView.startCompassFile();
        new Thread(new Runnable() {
            @Override
            public void run() {
                if (sensorStringBuilder.length() > 0) {
                    new SaveThread(wifiStringBuilder.toString(), beaconStringBuilder.toString(), sensorStringBuilder.toString()).run();
                    wifiStringBuilder.setLength(0);
                    beaconStringBuilder.setLength(0);
                    sensorStringBuilder.setLength(0);
                }

                try {
                    List<NexdCollectorResult> result = NexdApplication.getInstance().getSqlHelper().getIOSMess();
                    for (NexdCollectorResult nexdCollectorResult : result) {
                        iosStringBuilder.append(nexdCollectorResult.getSingleSourceAddress())
                                .append(" ")
                                .append(nexdCollectorResult.getSingleSourceUuid())
                                .append(" ")
                                .append(nexdCollectorResult.getSingleSourceMajor())
                                .append(" ")
                                .append(nexdCollectorResult.getSingleSourceMinor())
                                .append("\n");
                    }
                    FileUtil.writeFile(iosSavePath, iosStringBuilder.toString());
                    // 开始压缩文件, 先创建压缩目录
                    Logger.debug(TAG, "zipSavePath  " + zipSavePath);

                    FileUtil.archiveCompressFile(zipSrcSavePath, zipSavePath);
//                    FileUtil.compressFile(FileUtil.createFile(zipSrcSavePath), zipSavePath);
                    Logger.debug(TAG, "zipSrcSavePath" + zipSrcSavePath);
                    FileUtil.deleteFile(zipSrcSavePath);

                    ((Activity) context).runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            mainView.endCompassFile();
                        }
                    });
                } catch (Exception e) {
                    e.printStackTrace();
                    UMengUtil.getInstance().reportError(context, e);
                    NexdCrashException.getInstance().reportException(e);
                }
            }
        }).start();
    }

    private class EnvironmentCallBackRunnable extends TimerTask {

        @Override
        public void run() {
            ((Activity) context).runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mainView.updateEnvironment(String.valueOf(environmentParam));
                }
            });
        }
    }

    private class SaveThread implements Runnable {

        String wifi;
        String beacon;
        String sensor;

        SaveThread(String wifi, String beacon, String sensor) {
            this.wifi = wifi;
            this.beacon = beacon;
            this.sensor = sensor;
        }

        @Override
        public void run() {
            try {
                FileUtil.writeFile(wifiSavePath, wifi);
                FileUtil.writeFile(beaconSavePath, beacon);
                FileUtil.writeFile(sensorSavePath, sensor);
            } catch (IOException e) {
                e.printStackTrace();
                UMengUtil.getInstance().reportError(context, e);
                NexdCrashException.getInstance().reportException(e);
            }
        }
    }
}
